<template>
  <div id="WebGL-output"></div>
</template>

<script setup>
import {getCurrentInstance, onMounted, reactive} from 'vue';
import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls';

let {proxy} = getCurrentInstance();
let THREE = proxy.$THREE;

let scene = reactive({})
let camera = reactive({})
let renderer = reactive({})
let cube = reactive({})
// 初始化
function initThree() {
  // 创建场景
  scene = new THREE.Scene();
  // 创建照相机
  camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 10000);
  // 配置相机
  camera.position.set(200, 150, 200);// 相机在三维空间的位置
  // camera.lookAt(scene.position); // 将相机指向场景
  camera.lookAt(new THREE.Vector3(0, 0, 0)); // 相机看向空间坐标原点

  // 创建渲染器 (画布)
  renderer = new THREE.WebGLRenderer();
  // 配置渲染器
  renderer.antialias = true;// 抗锯齿
  renderer.autoClear = true;// 自动清除
  renderer.setClearColor(0x050505); // canvas画布颜色
  renderer.setSize(window.innerWidth, window.innerHeight); // canvas 画布大小
  renderer.shadowMap.enabled = true; // 让渲染器支持投影

  //辅助线 X轴是红色. Y轴是绿色. Z轴是蓝色
  const axes = new THREE.AxesHelper(100);
  scene.add(axes);

  createPlane(); //地面
  createCube(); //立方体
  createLight(); //灯光
  createPoint(); //光源

  // 将这个canvas元素插入到 html中
  document.getElementById('WebGL-output').appendChild(renderer.domElement);
  renderer.render(scene, camera)

  let controls = new OrbitControls(camera, renderer.domElement)
  controls.addEventListener('change', () => {
    renderer.render(scene, camera)
  })
}

// 创建立方体
function createCube() {
  let cubeGeometry = new THREE.BoxGeometry(40, 40, 40); //长宽高
  let cubeMaterial = new THREE.MeshLambertMaterial({color: Math.random() * 0xffffff}); //材质颜色
  cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
  cube.position.x = 20; //三轴的位置
  cube.position.y = 40;
  cube.position.z = -20;
  cube.castShadow = true; //立方体投影
  scene.add(cube);
}

// 创建灯光
function createLight() {
  const ambientLight = new THREE.AmbientLight({color: 0x404040});
  scene.add(ambientLight);
}

// 创建光源
function createPoint() {
  // 添加点光源
  let point = new THREE.SpotLight(0xcccccc); //设置灯光的颜色
  point.position.set(0, 300, 0); //点光源位置
  point.angle = Math.PI / 10; //设置投影的程度
  // point.shadow.mapSize.set(1024, 1024);
  scene.add(point);
  point.castShadow = true; //灯光投影
}

// 创建地面
function createPlane() {
  let planeGeometry = new THREE.PlaneGeometry(400, 400);   //地面的材质，宽高
  let planeMaterial = new THREE.MeshLambertMaterial({color: 0x6D6565});  // 创建地面
  let plane = new THREE.Mesh(planeGeometry, planeMaterial); // 设置地面的位置
  plane.rotation.x = -0.5 * Math.PI;
  plane.position.x = 0;
  plane.position.y = 0;
  plane.position.z = 0;
  plane.receiveShadow = true; //地面被投影
  scene.add(plane);  //将地面添加到坐标轴中
}

function render() {
  cube.rotation.x += 0.01
  cube.rotation.y += 0.01
  cube.rotation.z += 0.01
  // 开始渲染
  renderer.render(scene, camera);
}
function animate() {
  requestAnimationFrame(animate)
  render()
}
onMounted(() => {
  initThree()
  animate()
})
</script>

<style scoped>

</style>
